﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System.Text;

namespace RuoYi.Framework.Authentication.JwtBearer;

/// <summary>
/// JWT 授权服务拓展类
/// </summary>
public static class JwtBearerServiceCollectionExtensions
{
    /// <summary>
    /// 添加 JWT 授权
    /// </summary>
    /// <param name="services"></param>
    /// <param name="configuration"></param>
    /// <returns></returns>
    public static AuthenticationBuilder AddJwtBearer(this IServiceCollection services)
    {
        var jwtBearerOptions = App.GetConfig<JwtBearerOptions>("JwtBearer");

        return services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = jwtBearerOptions.ValidateIssuer,
                ValidateAudience = jwtBearerOptions.ValidateAudience,
                ValidateLifetime = jwtBearerOptions.ValidateLifetime,
                ValidateIssuerSigningKey = jwtBearerOptions.ValidateIssuerSigningKey,
                ValidIssuer = jwtBearerOptions.Issuer,
                ValidAudience = jwtBearerOptions.Audience,
                ClockSkew = TimeSpan.Zero,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtBearerOptions.SecretKey))
            };

            // 可选：处理某些事件
            options.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =>
                {
                    //优先Query中获取，再去cookies中获取
                    var accessToken = context.Request.Query["access_token"];
                    if (!string.IsNullOrEmpty(accessToken))
                    {
                        context.Token = accessToken;
                        return Task.CompletedTask;
                    }
                    if (context.Request.Cookies.TryGetValue("Admin-Token", out var cookiesToken))
                    {
                        context.Token = cookiesToken;
                    }
                    return Task.CompletedTask;
                }
            };
        })
        .AddJwtBearer("Refresh", options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = jwtBearerOptions.ValidateIssuer,
                ValidateAudience = jwtBearerOptions.ValidateAudience,
                ValidateLifetime = jwtBearerOptions.ValidateLifetime,
                ValidateIssuerSigningKey = jwtBearerOptions.ValidateIssuerSigningKey,
                ValidIssuer = jwtBearerOptions.Issuer,
                ValidAudience = jwtBearerOptions.Audience,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtBearerOptions.SecretKey))
            };
            options.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =>
                {
                    //优先Headers中获取，再去Query中获取
                    var refresh_token = context.Request.Headers["refresh_token"];
                    if (!string.IsNullOrEmpty(refresh_token))
                    {
                        context.Token = refresh_token;
                        return Task.CompletedTask;
                    }
                    var refreshToken = context.Request.Query["refresh_token"];
                    if (!string.IsNullOrEmpty(refreshToken))
                    {
                        context.Token = refreshToken;
                    }
                    return Task.CompletedTask;
                }
            };
        });
    }
}